using System;
using AntEater.ComponentModel.Validation;
using System.Collections.Generic;
using System.ComponentModel;
using System.Collections.ObjectModel;
using AntEater.ComponentModel.BuildElements.Design;
using System.Drawing.Design;

namespace AntEater.ComponentModel.BuildElements
{
    /// <summary>
    /// Provides the Task build element.
    /// </summary>
    [Serializable]
    [BuildElement("Task",HasDynamicElementName=true)]
    [ChildBuildElementType(typeof(OutputBuildElement))]
    [Icon(typeof(TaskBuildElement), "AntEater.ComponentModel.Resources.Task.ico")]
    public class TaskBuildElement : GenericContainerBuildElementBase
    {

        /// <summary>
        /// Initializes a new instance of the <see cref="T:TaskBuildElement"/> class.
        /// </summary>
        /// <param name="context">The context.</param>
        public TaskBuildElement(BuildFileDefinition context)
            : base(context) {
            this._parameters = new TaskParameterCollection();
            this._parameters.CollectionChanged += new EventHandler<CollectionChangeEventArgs>(ParametersCollectionChanged);

            this.Context.TaskNameChangeTracker.TrackedPropertyChanged += new EventHandler<TrackedPropertyChangedEventArgs>(TaskNameChangeTrackerTrackedPropertyChanged);
        }

        /// <summary>
        /// Gets or sets the name of the task.
        /// </summary>
        /// <value>The name of the task.</value>
        [BuildElementProperty("TaskName", false, BuildElementPropertyType.String)]
        [Description("Required attribute.\nThe name of the Task.")]
        [DisplayName("TaskName")]
        [Category("MsBuild")]
        [Editor(typeof(TaskTypeEditor), typeof(UITypeEditor))]
        public override string ElementName {
            get {
                return base.ElementName;
            }
            set {
                base.ElementName = value;
            }
        }

        private TaskParameterCollection _parameters;

        /// <summary>
        /// Gets or sets the parameters.
        /// </summary>
        /// <value>The parameters.</value>
        [BuildElementProperty("Parameters", false, BuildElementPropertyType.ListOfParameters)]
        [Description("Required if the task class contains one or more properties labeled with the [Required] attribute.\nA user-defined task parameter that contains the parameter value as its value. There can be any number of parameters in the Task element, with each attribute mapping to a .NET property in the task class.")]
        [Category("MsBuild")]
        public TaskParameterCollection Parameters {
            get { return _parameters; }
        }

        private string _condition;

        /// <summary>
        /// Gets or sets the condition.
        /// </summary>
        /// <value>The condition.</value>
        [BuildElementProperty("Condition", false, BuildElementPropertyType.Condition)]
        [Description("Optional attribute.\nCondition to be evaluated.")]
        [Category("MsBuild")]
        public string Condition {
            get { return _condition; }
            set {
                if (_condition != value) {
                    _condition = value;
                    OnPropertyChanged("Condition");
                }
            }
        }

        private string _continueOnError;

        /// <summary>
        /// Gets or sets a value indicating whether [continue on error].
        /// </summary>
        /// <value><c>true</c> if [continue on error]; otherwise, <c>false</c>.</value>
        [BuildElementProperty("ContinueOnError", false,BuildElementPropertyType.String)]
        [Description("Optional attribute.\nA Boolean attribute that defaults to false if not specified. If ContinueOnError is false and a task fails, the remaining tasks in the Target element are not executed and the entire Target element is considered to have failed.\nIf this attribute is true, subsequent tasks in the Target element continue to execute even if the current task fails, and all errors from the task are treated as warnings.")]
        [Category("MsBuild")]
        public string ContinueOnError {
            get { return _continueOnError; }
            set {
                if (_continueOnError != value) {
                    _continueOnError = value;
                    OnPropertyChanged("ContinueOnError");
                }
            }
        }

        /// <summary>
        /// Determines whether this instance is valid.
        /// </summary>
        /// <value></value>
        /// <returns>
        /// 	<c>true</c> if this instance is valid; otherwise, <c>false</c>.
        /// </returns>
        public override bool IsValid {
            get { throw new NotImplementedException(); }
        }

        /// <summary>
        /// Validates the specified recursive.
        /// </summary>
        /// <param name="recursive">if set to <c>true</c> [recursive].</param>
        /// <returns></returns>
        public override ReadOnlyCollection<ValidationResult> Validate(bool recursive) {
            throw new NotImplementedException();
        }

        /// <summary>
        /// Creates a new object that is a copy of the current instance.
        /// </summary>
        /// <returns>
        /// A new object that is a copy of this instance.
        /// </returns>
        public override object Clone() {
            TaskBuildElement newElement = base.Clone() as TaskBuildElement;

            if (this._condition != null) {
                newElement._condition = this._condition.ToString() as string;
            }
            if (this._continueOnError != null) {
                newElement._continueOnError = this._continueOnError.ToString() as string;
            }
            newElement._parameters.AddRange(this._parameters.Clone() as TaskParameterCollection);

            return newElement;
        }

        /// <summary>
        /// Parameterses the collection changed.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="T:System.ComponentModel.CollectionChangeEventArgs"/> instance containing the event data.</param>
        private void ParametersCollectionChanged(object sender, CollectionChangeEventArgs e) {
            OnPropertyChanged("Parameters");
        }

        /// <summary>
        /// Tasks the name change tracker tracked property changed.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="T:AntEater.ComponentModel.TrackedPropertyChangedEventArgs"/> instance containing the event data.</param>
        private void TaskNameChangeTrackerTrackedPropertyChanged(object sender, TrackedPropertyChangedEventArgs e) {
            if (this.ElementName == e.OldPropertyValue as string) {
                this.ElementName = e.NewPropertyValue as string;
            }
        }
    }
}
